package bid

import (
	"errors"
	"fmt"
	"github.com/gomodule/redigo/redis"
	"strings"
	"time"
	"wx-api/adx-bid/cache"
	"wx-api/adx-bid/config"
	"wx-api/adx-bid/model/m_adxapp"
	"wx-api/adx-bid/model/m_adxlist"
	"wx-api/adx-bid/model/m_adxslot"
	"wx-api/adx-bid/models/bid/BidModel"
	"wx-api/adx-bid/utils"
)

func MediaBodyDecode(body []byte, ty, cty string) (*BidModel.BidRequest, interface{}, string, error) {
	ret := &BidModel.BidRequest{}
	hty := "json"
	var err error
	var mreq interface{}
	switch ty {
	case "huayan":
		ret, mreq, hty, err = Huayan{}.DecodeReq(body, cty)
	case "360ad":
		ret, mreq, hty, err = M360AD{}.DecodeReq(body, cty)
	}
	if err != nil {
		return ret, nil, "", errors.New("MediaBodyDecode===" + ty + "=" + err.Error())
	}
	return ret, mreq, hty, nil
}

func MediaBodyEncode(mreq interface{}, res *BidModel.BidResponse, ty, cty string) (interface{}, error) {
	var ret interface{}
	var err error
	switch ty {
	case "huayan":
		ret, err = Huayan{}.EncodeRes(mreq, res, cty)
	case "360ad":
		ret, err = M360AD{}.EncodeRes(mreq, res, cty)
	}
	if err != nil {
		return ret, errors.New("MediaBodyEncode===" + ty + "=" + err.Error())
	}
	return ret, nil
}

// 媒体广告位查询
func SelSlot(sty string, a_info *m_adxlist.AdxList, req *BidModel.BidRequest) (*m_adxapp.AdxApp, *m_adxslot.AdxSlot, error) {

	imp := req.GetImp()[0]
	tagid := imp.GetTagid()
	if tagid == "" {
		return nil, nil, errors.New("SelSlot req imp tagid is empty")
	}
	s_info, ok := cache.CacheAdxSlotMapGet(sty + a_info.Uqid + tagid)
	if !ok || s_info == nil {
		return nil, nil, errors.New("SelSlot req imp tagid=" + sty + "=" + tagid + " not exist")
	}
	m_info, ok := cache.CacheAdxAppMapGet(sty + s_info.Mid)
	if !ok || m_info == nil {
		return nil, nil, errors.New("SelSlot req mid=" + sty + "=" + s_info.Mid + " not exist")
	}
	//广告位控量
	if s_info.ReqNum > 0 {
		s_key := "m-req-" + time.Now().Format("2006-01-02") + "-" + s_info.Uqid
		tmpnum, err_str := GetAdxRtbReqRedis(s_key)
		if err_str != "" {
			return nil, nil, errors.New("SelSlot req limit err:=" + sty + "=" + s_info.Mid + err_str)
		}
		if tmpnum >= s_info.ReqNum {
			return nil, nil, errors.New("SelSlot req limit =" + sty + "=" + s_info.Mid)
		}
		go SetAdxRtbReqRedis(s_key)
	}
	return m_info, s_info, nil
}

func GetAdxRtbReqRedis(key string) (int64, string) {
	conn := config.AdxRedisSlotLimit.Get()
	if conn == nil {
		return 0, "GetAdxRtbReqRedis redis init error"
	}
	defer conn.Close()
	vale, err := redis.Int64(conn.Do("GET", key))
	if err != nil {
		if errors.Is(err, redis.ErrNil) {
			return 0, ""
		}
		return 0, "GetAdxRtbReqRedis redis error2:" + err.Error()
	}
	return vale, ""
}

func ClearAdxRtbReqRedis() {
	conn := config.AdxRedisSlotLimit.Get()
	if conn == nil {
		return
	}
	defer conn.Close()
	sddd := []string{
		time.Now().AddDate(0, 0, -1).Format("2006-01-02"),
		time.Now().AddDate(0, 0, -2).Format("2006-01-02"),
	}
	for _, s := range sddd {
		arrs, err := redis.Strings(conn.Do("KEYS", "m-req-"+s+"-*"))
		if err != nil {
			fmt.Println("AdxRtbReqRedis clear error:", err.Error())
			continue
		}
		for _, a := range arrs {
			conn.Do("DEL", a)
		}
	}
}
func SetAdxRtbReqRedis(key string) {
	conn := config.AdxRedisSlotLimit.Get()
	if conn == nil {
		fmt.Println("SetAdxRtbReqRedis redis init error")
		return
	}
	defer conn.Close()
	_, err := conn.Do("INCR", key)
	if err != nil {
		fmt.Println("SetAdxRtbReqRedis :" + err.Error())
	}
	return
}

func MediaDoParam(req *BidModel.BidRequest) error {
	if len(req.GetImp()) == 0 {
		return errors.New("MediaDoParam req imp is 0")
	}
	if req.GetApp() == nil {
		return errors.New("MediaDoParam req app is nil")
	}
	if req.GetDevice() == nil {
		return errors.New("MediaDoParam req device is nil")
	}
	//imp := req.GetImp()[0]
	//if imp.GetBanner() == nil && imp.GetNative() == nil && imp.GetVideo() == nil {
	//	return errors.New("MediaDoParam req banner is nil")
	//}
	if req.GetDevice().GetIdfa() != "" && req.GetDevice().GetIdfaMd5() == "" {
		req.Device.IdfaMd5 = utils.MD5(req.GetDevice().GetIdfa())
	}
	if len(req.GetDevice().GetCaids()) > 0 {
		for i, caid := range req.GetDevice().GetCaids() {
			if caid.GetCaid() != "" && caid.GetCaidMd5() == "" {
				req.Device.Caids[i].CaidMd5 = utils.MD5(caid.GetCaid())
			}
		}
	}
	if req.GetDevice().GetImei() != "" && req.GetDevice().GetImeiMd5() == "" {
		req.Device.ImeiMd5 = utils.MD5(req.GetDevice().GetImei())
	}
	if req.GetDevice().GetOaid() != "" && req.GetDevice().GetOaidMd5() == "" {
		req.Device.OaidMd5 = utils.MD5(req.GetDevice().GetOaid())
	}
	if req.GetDevice().GetAndroidId() != "" && req.GetDevice().GetAndroidIdMd5() == "" {
		req.Device.AndroidIdMd5 = utils.MD5(req.GetDevice().GetAndroidId())
	}
	if req.GetDevice().GetMac() != "" && req.GetDevice().GetMacMd5() == "" {
		req.Device.MacMd5 = utils.MD5(req.GetDevice().GetMac())
	}
	os := strings.ToLower(req.GetDevice().GetOs())
	if os == "" {
		return errors.New("MediaDoParam req device os is empty")
	}
	if req.GetDevice().GetOs() != "ios" && req.GetDevice().GetOs() != "android" && req.GetDevice().GetOs() != "harmonyos" {
		return errors.New("MediaDoParam req device os is error:" + os)
	}
	if req.GetDevice().GetOs() == "ios" {
		if req.GetDevice().GetIdfa() == "" && req.GetDevice().GetIdfaMd5() == "" && len(req.GetDevice().GetCaids()) == 0 {
			return errors.New("MediaDoParam req device ios did is empty")
		}
		return nil
	}
	if req.GetDevice().GetImei() == "" && req.GetDevice().GetImeiMd5() == "" && req.GetDevice().GetOaid() == "" && req.GetDevice().GetOaidMd5() == "" && req.GetDevice().GetAndroidId() == "" && req.GetDevice().GetAndroidIdMd5() == "" {
		return errors.New("MediaDoParam req device ios did is empty")
	}
	return nil
}
